package pl.edu.wsinf.lukaszwalczak.emailclient.view;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ComboBoxBuilder;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.web.HTMLEditor;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import pl.edu.wsinf.lukaszwalczak.emailclient.controller.MailCreateController;
import pl.edu.wsinf.lukaszwalczak.emailclient.pojo.Account;
import pl.edu.wsinf.lukaszwalczak.emailclient.pojo.Mail;

@Component
public class MailCreateView {

    @Inject
    private MailCreateController controller;
    private Stage stage = null;
    private ComboBox<Account> fromComboBox;
    private Account from = null;
    private TextField to;
    private TextField cc;
    private TextField subject;
    private HTMLEditor editor = null;
    private ObservableList<AttachmentEntry> attachments = FXCollections.<AttachmentEntry>observableArrayList();

    public void show(Mail mail) {
        if (stage == null) {
            stage = new Stage();
            //resizable disabled
            stage.setResizable(false);
            //create root node of scene, i.e. group
            AnchorPane root = new AnchorPane();
            //create scene with set width, height and color
            Scene scene = new Scene(root, 700, 600, Color.WHITESMOKE);
            //set scene to stage
            stage.setScene(scene);
            stage.setTitle("Nowa wiadomość");
            //center stage on screen
            stage.centerOnScreen();
            //show the stage
            stage.show();

            int LEFT_PADDING = 20;
            int RIGHT_PADDING = 20;
            int TOP_PADDING = 15;
            int BOTTOM_PADDING = 15;
            int FIELD_SPACING = 25;
            int LABEL_WIDTH = 150;
            int TEXT_FIELD_WIDTH = 530;

            // Pole "Adres email"
            Label emailLabel = new Label("Do: ");
            emailLabel.setPrefWidth(LABEL_WIDTH);
            to = new TextField();
            to.setPrefWidth(TEXT_FIELD_WIDTH - 45);

            // Pole "Adres email"
            Label emailLabel1 = new Label("Kopia: ");
            emailLabel1.setPrefWidth(LABEL_WIDTH);
            cc = new TextField();
            cc.setPrefWidth(TEXT_FIELD_WIDTH - 45);

            // Pole "Temat"
            Label emailLabel2 = new Label("Temat: ");
            emailLabel2.setPrefWidth(LABEL_WIDTH);
            subject = new TextField();
            subject.setPrefWidth(TEXT_FIELD_WIDTH);

            // Pole "Od"
            Label emailLabel3 = new Label("Od: ");
            emailLabel3.setPrefWidth(LABEL_WIDTH);

            // Przycisk "Dodaj"
            Button btn = ViewHelper.createButton(null, new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                }
            }, "user-add.png", null, 10d);

            // Załączniki
            ListView<AttachmentEntry> attachmentsList = new ListView<>(attachments);
            attachmentsList.setOrientation(Orientation.VERTICAL);
            attachmentsList.setPrefWidth(TEXT_FIELD_WIDTH);
            attachmentsList.setPrefHeight(50);

            Button attachmentsButton = ViewHelper.createButton("Załącznik", new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    FileChooser fileChooser = new FileChooser();

                    //Show open file dialog
                    File file = fileChooser.showOpenDialog(stage);
                    if (file != null) {
                        attachments.add(new AttachmentEntry(file));
                    }
                }
            }, "attachment.png", 120d, null);

            // Przycisk "Wyślij"
            Button btn1 = ViewHelper.createButton("Wyślij", new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    if (from != null) {
                        Mail mail = controller.save(from, getValues());
                        controller.send(mail);
                        stage.close();
                    }
                }
            }, "mail_send.png", 100d, 30d);

            // Przycisk "Zapisz"
            Button btn3 = ViewHelper.createButton("Zapisz", new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    if (from != null) {
                        controller.save(from, getValues());
                        stage.close();
                    }
                }
            }, "save.png", 100d, 30d);

            VBox vRoot = new VBox();
            vRoot.setPadding(new Insets(170, 0, 0, 0));
            vRoot.setSpacing(5);

            // Przycisk "Dodaj"
            Button btn5 = ViewHelper.createButton(null, new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                }
            }, "user-add.png", null, 10d);

            editor = new HTMLEditor();
            editor.setPrefSize(700, 360);
            vRoot.getChildren().add(editor);

            final Label htmlLabel = new Label();
            htmlLabel.setMaxWidth(400);
            htmlLabel.setWrapText(true);
            root.getChildren().addAll(vRoot);

            StringConverter converter = new StringConverter<Account>() {
                @Override
                public String toString(Account t) {
                    return t.getEmailAddress();
                }

                @Override
                public Account fromString(String string) {
                    return fromComboBox.getValue();
                }
            };

            fromComboBox = ComboBoxBuilder.<Account>create().
                    promptText("Wybierz konto").
                    items(FXCollections.observableArrayList(controller.getAccounts())).
                    converter(converter).
                    build();
            fromComboBox.setPrefWidth(TEXT_FIELD_WIDTH);
            fromComboBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Account>() {
                @Override
                public void changed(ObservableValue<? extends Account> ov, Account t, Account t1) {
                    from = t1;
                }
            });

            root.getChildren().addAll(emailLabel, to, emailLabel1, cc, emailLabel2, subject, attachmentsList, emailLabel3, btn, btn1, attachmentsButton, btn3, btn5, fromComboBox);

            AnchorPane.setTopAnchor(emailLabel3, Double.valueOf(TOP_PADDING));
            AnchorPane.setLeftAnchor(emailLabel3, Double.valueOf(LEFT_PADDING));
            AnchorPane.setTopAnchor(fromComboBox, Double.valueOf(TOP_PADDING));
            AnchorPane.setLeftAnchor(fromComboBox, Double.valueOf(LABEL_WIDTH));
            AnchorPane.setTopAnchor(emailLabel, Double.valueOf(TOP_PADDING + 1 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(emailLabel, Double.valueOf(LEFT_PADDING));
            AnchorPane.setTopAnchor(to, Double.valueOf(TOP_PADDING + 1 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(to, Double.valueOf(LABEL_WIDTH));
            AnchorPane.setTopAnchor(emailLabel1, Double.valueOf(TOP_PADDING + 2 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(emailLabel1, Double.valueOf(LEFT_PADDING));
            AnchorPane.setTopAnchor(cc, Double.valueOf(TOP_PADDING + 2 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(cc, Double.valueOf(LABEL_WIDTH));
            AnchorPane.setTopAnchor(emailLabel2, Double.valueOf(TOP_PADDING + 3 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(emailLabel2, Double.valueOf(LEFT_PADDING));
            AnchorPane.setTopAnchor(subject, Double.valueOf(TOP_PADDING + 3 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(subject, Double.valueOf(LABEL_WIDTH));
            AnchorPane.setTopAnchor(attachmentsList, Double.valueOf(TOP_PADDING + 4 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(attachmentsList, Double.valueOf(LABEL_WIDTH));

            AnchorPane.setTopAnchor(btn, Double.valueOf(BOTTOM_PADDING + 1 * FIELD_SPACING));
            AnchorPane.setRightAnchor(btn, Double.valueOf(RIGHT_PADDING));
            AnchorPane.setTopAnchor(btn5, Double.valueOf(BOTTOM_PADDING + 2 * FIELD_SPACING));
            AnchorPane.setRightAnchor(btn5, Double.valueOf(RIGHT_PADDING));
            AnchorPane.setBottomAnchor(btn1, Double.valueOf(BOTTOM_PADDING));
            AnchorPane.setRightAnchor(btn1, Double.valueOf(RIGHT_PADDING));
            AnchorPane.setTopAnchor(attachmentsButton, Double.valueOf(BOTTOM_PADDING + 4 * FIELD_SPACING));
            AnchorPane.setLeftAnchor(attachmentsButton, Double.valueOf(LEFT_PADDING));
            AnchorPane.setBottomAnchor(btn3, Double.valueOf(BOTTOM_PADDING));
            AnchorPane.setLeftAnchor(btn3, Double.valueOf(LEFT_PADDING));

        } else {
            stage.show();
        }
        to.setText("");
        cc.setText("");
        subject.setText("");
        editor.setHtmlText("");
        if (mail != null) {
            from = mail.getAccount();
        } else {
            from = null;
        }
        fromComboBox.setValue(from);
        attachments.clear();
    }

    public Map<String, Object> getValues() {
        Map<String, Object> values = new HashMap<>();

        String toValue = to.getText();
        if (toValue != null) {
            values.put("to", new HashSet<>(Arrays.asList(toValue.replaceAll("\\s", "").split(","))));
        } else {
            values.put("to", Collections.emptySet());
        }

        String ccValue = cc.getText();
        if (ccValue != null) {
            values.put("cc", new HashSet<>(Arrays.asList(ccValue.replaceAll("\\s", "").split(","))));
        } else {
            values.put("cc", Collections.emptySet());
        }

        values.put("subject", subject.getText());
        values.put("content", editor.getHtmlText());

        if (!attachments.isEmpty()) {
            List<File> files = new ArrayList<>();
            for (AttachmentEntry ae : attachments) {
                files.add(ae.getFile());
            }
            values.put("attachments", files);
        }

        return values;
    }

    public void setValues(Map<String, Object> values) {
        if (values.containsKey("to")) {
            Set<String> toValue = (Set<String>) values.get("to");
            to.setText(StringUtils.arrayToCommaDelimitedString(toValue.toArray()));
        }
        if (values.containsKey("cc")) {
            Set<String> ccValue = (Set<String>) values.get("cc");
            cc.setText(StringUtils.arrayToCommaDelimitedString(ccValue.toArray()));
        }
        if (values.containsKey("subject")) {
            subject.setText((String) values.get("subject"));
        }
        if (values.containsKey("content")) {
            editor.setHtmlText((String) values.get("content"));
        }
    }

    private static class AttachmentEntry {

        private String fileName;
        private File file;
        private boolean checked = true;

        public AttachmentEntry(File file) {
            this.file = file;

            if (file.getName() != null) {
                fileName = file.getName();
            }
        }

        public String getFileName() {
            return fileName;
        }

        public void setFileName(String fileName) {
            this.fileName = fileName;
        }

        public File getFile() {
            return file;
        }

        public void setFile(File file) {
            this.file = file;
        }

        public boolean isChecked() {
            return checked;
        }

        public void setChecked(boolean checked) {
            this.checked = checked;
        }

        @Override
        public String toString() {
            return fileName;
        }
    }
}
